package cn.ug.activity.mq;

import cn.ug.activity.bean.CertificateBean;
import cn.ug.activity.bean.DisplayLinkParamBean;
import cn.ug.activity.mapper.entity.Contract;
import cn.ug.activity.service.ContractService;
import cn.ug.activity.web.utils.ESignHelper;
import cn.ug.activity.web.utils.UploadUtil;
import cn.ug.bean.base.SerializeObject;
import cn.ug.bean.type.ResultType;
import cn.ug.config.AplicationResourceProperties;
import cn.ug.enums.ProductTypeEnum;
import cn.ug.feign.MemberUserService;
import cn.ug.member.bean.response.MemberUserBean;
import cn.ug.util.BigDecimalUtil;
import com.alibaba.fastjson.JSONObject;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.timevale.esign.sdk.tech.bean.result.AddSealResult;
import com.timevale.esign.sdk.tech.bean.result.FileDigestSignResult;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.amqp.rabbit.annotation.RabbitHandler;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

import static cn.ug.config.QueueName.QUEUE_ESIGN_CONTRACT;
import static cn.ug.util.ConstantUtil.SLASH;
import static cn.ug.util.RedisConstantUtil.ESIGN_ERROR_KEY;

@Component
@RabbitListener(queues = QUEUE_ESIGN_CONTRACT)
public class EsignContractReceiver {
    private Log log = LogFactory.getLog(DonationCashReceiver.class);
    private ObjectMapper mapper = new ObjectMapper();
    @Autowired
    private MemberUserService memberUserService;
    @Autowired
    protected AplicationResourceProperties properties;
    @Autowired
    private ContractService contractService;
    @Autowired
    private RedisTemplate<String, String> redisTemplate;

    private static final String REMARK_YES = "是";
    private static final String REMARK_NO = "否";
    @RabbitHandler
    public void process(ContractMQ o) throws JsonProcessingException {
        log.info("EsignContractReceiver:process.......................");
        log.info("电子签名参数：=" + JSONObject.toJSONString(o));
        if (o == null || StringUtils.isBlank(o.getProductName()) || StringUtils.isBlank(o.getMemberId())) {
            return;
        }
        /*if (o.getProductType() != ProductTypeEnum.REGULAR.getType()) {
            return;
        }
        if (o.getIsActivity() != 2) {
            return;
        }*/
        //{"productId":"AtkxZy7u3Z6NgQkJYhiAaV","productName":"不限制","productType":6,"investDay":0,"tradeDate":"2018-12-10","memberId":"7oqomQAYjT7CScMyeHEzBS","price":278.57,"weight":1,"specification":1,"tradeAmount":278.57,"orderNO":"201812101729076890","isActivity":2}
        String key = ESIGN_ERROR_KEY + o.getOrderNO();
        String value = redisTemplate.opsForValue().get(key);
        if (StringUtils.isNotBlank(value)) {
            int num = Integer.parseInt(value);
            if (num > 5) {
                return;
            }
        }
        log.info(mapper.writeValueAsString(o));
        SerializeObject<MemberUserBean> userBean = memberUserService.findById(o.getMemberId());
        if (null == userBean || userBean.getCode() != ResultType.NORMAL || userBean.getData() == null) {
            throw new RuntimeException("生成e签宝合同，获取用户信息失败。");
        }
        MemberUserBean user = userBean.getData();
        ESignHelper.initProject(properties.getProjectId(), properties.getProjectSecret(), properties.getApiUrl());
        String accountId = ESignHelper.createPersonAccount(user.getMobile(), user.getName(), user.getIdCard());
        String organId = ESignHelper.createOrganizeAccount(properties.getOrganName(), properties.getOrganCode(), properties.getLegalName(), properties.getLegalIdcard());
        AddSealResult userPersonSealData = ESignHelper.addPersonTemplateSeal(accountId);
        if (userPersonSealData == null) {
            String numValue = redisTemplate.opsForValue().get(key);
            if (StringUtils.isNotBlank(numValue)) {
                int num = Integer.parseInt(numValue);
                num++;
                redisTemplate.opsForValue().set(key, String.valueOf(num), 3600, TimeUnit.SECONDS);
            } else {
                redisTemplate.opsForValue().set(key, String.valueOf(1), 3600, TimeUnit.SECONDS);
            }
        }
        ESignHelper.addOrganizeTemplateSeal(organId, "", properties.getLowboomText());

        Map<String, Object> map = new HashMap<>();
        //非安稳金产品
        if (ProductTypeEnum.SMOOTH_GOLD.getType() != o.getProductType()) {
            map.put("companyName", properties.getOrganName());
            map.put("address", properties.getAddress());
            map.put("legalPerson", properties.getLegalName());
            map.put("userName", user.getName());
            map.put("idcard", user.getIdCard());
            map.put("mobile", user.getMobile());
            map.put("productName", o.getProductName());
            map.put("price", o.getPrice());
            map.put("totalGram", String.valueOf(o.getWeight()));
            map.put("specification", String.valueOf(o.getSpecification()));
        } else {
            //合同编号
            map.put("tbOrderNo", o.getOrderNO());
            //签定时间
            map.put("date", o.getTradeDate());
            //甲方名称
            map.put("userName", user.getName());
            //身份证
            map.put("idCard", user.getIdCard());
            //联系电话
            map.put("mobile", user.getMobile());
            //购买克重
            map.put("totalGram", String.valueOf(o.getWeight()));
            //金价
            map.put("price", o.getPrice());

            map.put("flagA", REMARK_NO);
            map.put("flagB", REMARK_NO);
            map.put("flagC", REMARK_NO);
            map.put("flagD", REMARK_NO);
            //期限---打钩的那种
            switch (o.getInvestDay()) {
                case 90:
                    map.put("flagA", REMARK_YES);
                    break;
                case 180:
                    map.put("flagB", REMARK_YES);
                    break;
                case 270:
                    map.put("flagC", REMARK_YES);
                    break;
                case 360:
                    map.put("flagD", REMARK_YES);
                    break;
            }
            //回租开始时间-回租结束时间
            if (StringUtils.isNotBlank(o.getLbStartTime())) {
                String[] info = StringUtils.split(o.getLbStartTime().substring(0, 10), "-");
                if (info != null && info.length == 3) {
                    map.put("lbYears", info[0]);
                    map.put("IbMonths", String.valueOf(Integer.parseInt(info[1])));
                    map.put("IbDays", String.valueOf(Integer.parseInt(info[2])));
                }
            }

            if (StringUtils.isNotBlank(o.getLbEndTime())) {
                String[] info = StringUtils.split(o.getLbEndTime().substring(0, 10), "-");
                if (info != null && info.length == 3) {
                    map.put("IbYeare", info[0]);
                    map.put("IbMonthe", String.valueOf(Integer.parseInt(info[1])));
                    map.put("IbDaye", String.valueOf(Integer.parseInt(info[2])));
                }
            }
            //甲方签字
            map.put("signNameA", user.getName());
            //甲方签署日期
            map.put("signDateA", o.getTradeDate());
            //乙方 授权代表签字
            map.put("signNameB", properties.getLegalName());
            //乙方签署日期
            map.put("signDateB", o.getTradeDate());
            /**********安稳金订购合同附表************/
            //购买克重
            map.put("bugGram", String.valueOf(o.getWeight()));
            //预期收益
            map.put("incomeGram", String.valueOf(o.getIncomeGram()));
        }

        //总计金额
        if (o.getTradeAmount() != null) {
            map.put("totalAmount", String.valueOf(o.getTradeAmount().doubleValue()));
            //总计金额 --金额大写
            map.put("totalAmountD", BigDecimalUtil.number2CNMontrayUnit(o.getTradeAmount()));
        } else {
            map.put("totalAmount", "--");
        }
        if (StringUtils.isNotBlank(o.getTradeDate())) {
            String[] info = StringUtils.split(o.getTradeDate(), "-");
            if (info != null && info.length == 3) {
                map.put("year", info[0]);
                map.put("month", String.valueOf(Integer.parseInt(info[1])));
                map.put("day", String.valueOf(Integer.parseInt(info[2])));
            }
        }
        FileDigestSignResult userPersonSignResult = null;
        if (ProductTypeEnum.SMOOTH_GOLD.getType() != o.getProductType()) {
            userPersonSignResult = ESignHelper.padData(ESignHelper.getBytes(properties.getTemplateUrl() + "/template.pdf"), accountId, userPersonSealData.getSealData(), map);
        } else {
            userPersonSignResult = ESignHelper.padData(ESignHelper.getBytes(properties.getTemplateUrl() + "/template-smooth.pdf"), accountId, userPersonSealData.getSealData(), map);
        }
        if (userPersonSignResult == null) {
            String numValue = redisTemplate.opsForValue().get(key);
            if (StringUtils.isNotBlank(numValue)) {
                int num = Integer.parseInt(numValue);
                num++;
                redisTemplate.opsForValue().set(key, String.valueOf(num), 3600, TimeUnit.SECONDS);
            } else {
                redisTemplate.opsForValue().set(key, String.valueOf(1), 3600, TimeUnit.SECONDS);
            }
        }
        FileDigestSignResult platformSignResult = null;
        if (ProductTypeEnum.SMOOTH_GOLD.getType() != o.getProductType()) {
            platformSignResult = ESignHelper.platformSignByStreamm(userPersonSignResult.getStream());
        } else {
            platformSignResult = ESignHelper.platformSignByStreammSmooth(userPersonSignResult.getStream());
        }

        if (0 == userPersonSignResult.getErrCode()) {
            String signServiceId = userPersonSignResult.getSignServiceId();
            String orderId = o.getOrderNO();
            String fileName = orderId + ".pdf";
            String filePath = properties.getTemplateUrl() + SLASH + fileName;
            String url = "";
            String esignUrl = "";
            try {
                ESignHelper.saveSignedByStream(platformSignResult.getStream(), properties.getTemplateUrl(), fileName);
                url = UploadUtil.upload(properties.getAccessKey(), properties.getSecretKey(), properties.getBucket(), filePath, fileName, properties.getFileDomain());
                String businessTempletId = ESignHelper.createIndustryType(properties.getProjectId(), properties.getProjectSecret(), properties.getIndustry(), properties.getBusTypeUrl());
                String sceneTempletId = ESignHelper.createSceneType(properties.getProjectId(), properties.getProjectSecret(), businessTempletId, properties.getScene(), properties.getSceneTypeUrl());
                String segmentTempletId = ESignHelper.createSegmentType(properties.getProjectId(), properties.getProjectSecret(), sceneTempletId, properties.getSegment(), properties.getSegTypeUrl());
                DisplayLinkParamBean displayLinkParamRealName1 = new DisplayLinkParamBean();
                displayLinkParamRealName1.setDisplayName("甲方");
                displayLinkParamRealName1.setParamName("realName1");

                DisplayLinkParamBean displayLinkParamUserName1 = new DisplayLinkParamBean();
                displayLinkParamUserName1.setDisplayName("住址");
                displayLinkParamUserName1.setParamName("userName1");

                DisplayLinkParamBean displayLinkParamRealName2 = new DisplayLinkParamBean();
                displayLinkParamRealName2.setDisplayName("乙方");
                displayLinkParamRealName2.setParamName("realName2");

                DisplayLinkParamBean displayLinkParamUserName2 = new DisplayLinkParamBean();
                displayLinkParamUserName2.setDisplayName("身份证号码");
                displayLinkParamUserName2.setParamName("userName2");

                ArrayList<DisplayLinkParamBean> segmentProp = new ArrayList<DisplayLinkParamBean>();
                segmentProp.add(displayLinkParamRealName1);
                segmentProp.add(displayLinkParamUserName1);
                segmentProp.add(displayLinkParamRealName2);
                segmentProp.add(displayLinkParamUserName2);
                ESignHelper.createSegmentPropType(properties.getProjectId(), properties.getProjectSecret(), segmentTempletId, segmentProp, properties.getSegpropUrl());
                String sceneEvId = ESignHelper.createChainOfEvidence(sceneTempletId, o.getProductName() + "购买协议", properties.getProjectId(), properties.getProjectSecret(), properties.getVoucherUrl());
                JSONObject segmentDataJSON = new JSONObject();
                segmentDataJSON.put("realName1", properties.getOrganName());
                segmentDataJSON.put("userName1", properties.getAddress());
                segmentDataJSON.put("realName2", user.getName());
                segmentDataJSON.put("userName2", user.getIdCard());
                String segmentData = segmentDataJSON.toString();
                JSONObject result = ESignHelper.createSegmentOriginalStandard(properties.getProjectId(), properties.getProjectSecret(), segmentData, filePath, segmentTempletId, properties.getSimulateUrl());
                String evId = result.getString("evid");
                String fileUploadUrl = result.getString("url");
                ESignHelper.uploadOriginalDocumen(evId, fileUploadUrl, filePath);
                ESignHelper.appendEvidence(properties.getProjectId(), properties.getProjectSecret(), sceneEvId, evId, properties.getAppendVoucherUrl(), signServiceId);

                List<CertificateBean> certificates = new ArrayList<CertificateBean>();
                CertificateBean personBean = new CertificateBean();
                personBean.setName(properties.getOrganName());
                personBean.setType("CODE_USC");
                personBean.setNumber(properties.getOrganCode());
                CertificateBean orgBean = new CertificateBean();
                orgBean.setName(user.getName());
                orgBean.setType("ID_CARD");
                orgBean.setNumber(user.getIdCard());

                certificates.add(personBean);
                certificates.add(orgBean);
                ESignHelper.relateSceneEvIdWithUser(properties.getProjectId(), properties.getProjectSecret(), sceneEvId, certificates, properties.getRelateUrl());
                esignUrl = ESignHelper.getViewCertificateInfoUrl(properties.getProjectId(), properties.getProjectSecret(), sceneEvId, user.getIdCard(), properties.getViewpageUrl());
            } catch (Exception e) {

            }
            if (StringUtils.isBlank(url)) {
                log.info("e签宝合同上传失败。");
            }
            Contract contract = new Contract();
            contract.setOrderId(orderId);
            contract.setOriginalUrl(url);
            contract.setThirdpartyUrl(esignUrl);
            contractService.save(contract);
        } else {
            String numValue = redisTemplate.opsForValue().get(key);
            if (StringUtils.isNotBlank(numValue)) {
                int num = Integer.parseInt(numValue);
                num++;
                redisTemplate.opsForValue().set(key, String.valueOf(num), 3600, TimeUnit.SECONDS);
            } else {
                redisTemplate.opsForValue().set(key, String.valueOf(1), 3600, TimeUnit.SECONDS);
            }
            throw new RuntimeException("生成e签宝合同签署失败。");
        }
    }
}
